/*
 *  ppm.c
 *  libCV
 *
 *  Created by Gregory Koch on 05/03/11.
 *  Copyright 2011 IFlyBotIV. All rights reserved.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include "ppm.h"

ppm_t init_ppm(char* magic_number, unsigned char* datas, cvSize_t size)
{
	ppm_t ppm;
	
	strcpy(ppm.magic_number, magic_number);
	
	ppm.height = size.height;
	ppm.width = size.width;
	
	if(!datas)
	{
		if(!strcmp(ppm.magic_number, PPM_GREYSCALE))
		{
			ppm.max_val = 255;
			ppm.datas = malloc(ppm.width * ppm.height * sizeof(char));
			if(ppm.datas == NULL)
			{
				perror("malloc()");
				exit(EXIT_FAILURE);
			}	
		}
		else if(!strcmp(ppm.magic_number, PPM_BINARY))
		{
			ppm.max_val = 1;
			ppm.datas = malloc(ppm.width * ppm.height * sizeof(char));
			if(ppm.datas == NULL)
			{
				perror("malloc()");
				exit(EXIT_FAILURE);
			}		
		}
		else if(!strcmp(ppm.magic_number, PPM_COLOR))
		{
			ppm.max_val = 255;
			ppm.datas = malloc(ppm.width * ppm.height * sizeof(char) * 3);
			if(ppm.datas == NULL)
			{
				perror("malloc()");
				exit(EXIT_FAILURE);
			}	
		}
	}
	else
	{
		if(!strcmp(ppm.magic_number, PPM_GREYSCALE))
		{
			ppm.max_val = 255;
		}
		else if(!strcmp(ppm.magic_number, PPM_BINARY))
		{
			ppm.max_val = 1;
		}
		else if(!strcmp(ppm.magic_number, PPM_COLOR))
		{
			ppm.max_val = 255;
		}
		ppm.datas = datas;
	}
    
	return ppm;
}

void free_ppm(ppm_t ppm)
{
	if(ppm.datas)
		free(ppm.datas);
}

ppm_t read_ppm(char *file)
{
	ppm_t ppm;
	FILE* f;
	unsigned int i, val;
	
	if((f = fopen(file,"r"))==NULL)
    {
		perror("fopen()");
		exit(EXIT_FAILURE);
    }
	
	/* 
	 * Read magic number 
	 */
	fscanf(f, "%s", ppm.magic_number);
	
	/*
	 * Read width and height
	 */
	fscanf(f, "%u %u", &(ppm.width), &(ppm.height));
	
	/*
	 * Read max_val 
	 */
	fscanf(f, "%u", &(ppm.max_val));
	
	
	/*
	 * Read datas
	 */
	if(!strcmp(ppm.magic_number, PPM_GREYSCALE) || !strcmp(ppm.magic_number, PPM_BINARY))
    {
		/* 
		 * allocation 
		 */
		ppm.datas = malloc(ppm.width * ppm.height * sizeof(char));
		if(ppm.datas == NULL)
		{
			perror("malloc()");
			exit(EXIT_FAILURE);
		}
		
		for(i = 0; i < ppm.width * ppm.height; i++)
		{
			fscanf(f, "%i", &val);
			ppm.datas[i] = (unsigned char)val;
		}
    }
	else if(!strcmp(ppm.magic_number, PPM_COLOR))
    {
		/* 
		 * allocation 
		 */
		ppm.datas = malloc(ppm.width * ppm.height * sizeof(char) * 3);
		if(ppm.datas == NULL)
		{
			perror("malloc()");
			exit(EXIT_FAILURE);
		}
		
		for(i = 0; i < 3 * ppm.width * ppm.height; i++)
		{
			fscanf(f, "%i", &val);
			ppm.datas[i] = (unsigned char)val;
		}
    }
	else
	{
		perror("libCV : Unknow ppm magic number");
		exit(EXIT_FAILURE);
	}
	
	if(fclose(f)==EOF)
    {
		perror("fclose()");
		exit(EXIT_FAILURE);
    }
	
	return ppm;
}

void write_ppm(ppm_t ppm, char *file)
{
	
	FILE* f;
	unsigned int i;
	
	if((f = fopen(file,"w+"))==NULL)
    {
		perror("fopen()");
		exit(EXIT_FAILURE);
    }
	
	/*
	 * Write magic number 
	 */
	fprintf(f, "%s\n", ppm.magic_number);
	
	/*
	 * Write width and height
	 */
	fprintf(f, "%u %u\n", ppm.width, ppm.height);
	
	/*
	 * Write max_val 
	 */
	fprintf(f, "%u\n", ppm.max_val);
	
	/*
	 * Write image
	 */
	if(!strcmp(ppm.magic_number, PPM_GREYSCALE) || 
	   !strcmp(ppm.magic_number, PPM_BINARY))
    {
		for(i = 0; i < ppm.width * ppm.height; i++)
		{
			fprintf(f, "%i\n", ppm.datas[i]);
		}
    }
	else if(!strcmp(ppm.magic_number, PPM_COLOR))
    {
		for(i = 0; i < ppm.width * ppm.height * 3; i++)
		{
			fprintf(f, "%i\n", ppm.datas[i]);
		}
    }
	else
	{
		perror("libCV : Unknow ppm magic number");
		exit(EXIT_FAILURE);
	}
	
	if(fclose(f)==EOF)
    {
		perror("fclose()");
		exit(EXIT_FAILURE);
    }
	
}

void write_image2ppm(image_t img, char *file)
{
	FILE* f;
	int x, y, pos;
	
	if((f = fopen(file,"w+"))==NULL)
    {
		perror("fopen()");
		exit(EXIT_FAILURE);
    }
	
	if(img.type == IMG_BGR24)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_COLOR);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", img.size.width, img.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "255\n");
		
		for(y=0; y<img.size.height; y++)
		{
			for(x=0; x<img.size.width; x++)
			{
				pos = img.stride * y + x * 3;
				fprintf(f, "%i\n%i\n%i\n", img.data[pos+2], img.data[pos+1], img.data[pos]);
			}
		}
		
	}
	else if(img.type == IMG_RGB24)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_COLOR);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", img.size.width, img.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "255\n");
		
		for(y=0; y<img.size.height; y++)
		{
			for(x=0; x<img.size.width; x++)
			{
				pos = img.stride * y + x * 3;
				fprintf(f, "%i\n%i\n%i\n", img.data[pos], img.data[pos+1], img.data[pos+2]);
			}
		}
		
	}
	else if(img.type == IMG_BINARY8)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_BINARY);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", img.size.width, img.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "1\n");
		
		for(y=0; y<img.size.height; y++)
		{
			for(x=0; x<img.size.width; x++)
			{
				pos = img.stride * y + x;
				fprintf(f, "%i\n", img.data[pos]);
			}
		}
	}
	else if(img.type == IMG_GREYSCALE8)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_GREYSCALE);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", img.size.width, img.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "255\n");
		
		for(y=0; y<img.size.height; y++)
		{
			for(x=0; x<img.size.width; x++)
			{
				pos = img.stride * y + x;
				fprintf(f, "%i\n", img.data[pos]);
			}
		}
	}
	else
	{
		perror("libCV : Unknow image type");
		exit(EXIT_FAILURE);
	}
	
	if(fclose(f)==EOF)
    {
		perror("fclose()");
		exit(EXIT_FAILURE);
    }
}

void write_zone2ppm(zone_t zone, image_t img, char *file)
{
	FILE* f;
	int x, y, pos;
	
	if((f = fopen(file,"w+"))==NULL)
    {
		perror("fopen()");
		exit(EXIT_FAILURE);
    }
	
	
	if(img.type == IMG_BGR24)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_COLOR);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", zone.size.width, zone.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "255\n");
		
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				pos = img.stride * (zone.pos.y + y) + (zone.pos.x + x) * 3;
				fprintf(f, "%i\n%i\n%i\n", img.data[pos+2], img.data[pos+1], img.data[pos]);
			}
		}
	}
	else if(img.type == IMG_RGB24)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_COLOR);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", zone.size.width, zone.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "255\n");
		
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				pos = img.stride * (zone.pos.y + y) + (zone.pos.x + x) * 3;
				fprintf(f, "%i\n%i\n%i\n", img.data[pos], img.data[pos+1], img.data[pos+2]);
			}
		}
	}
	else if(img.type == IMG_BINARY8)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_BINARY);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", zone.size.width, zone.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "1\n");
		
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				pos = img.stride * (zone.pos.y + y) + (zone.pos.x + x);
				fprintf(f, "%i\n", img.data[pos]);
			}
		}
	}
	else if(img.type == IMG_GREYSCALE8)
	{
		/*
		 * Write magic number 
		 */
		fprintf(f, "%s\n", PPM_GREYSCALE);
		
		/*
		 * Write width and height
		 */
		fprintf(f, "%u %u\n", zone.size.width, zone.size.height);
		
		/*
		 * Write max_val 
		 */
		fprintf(f, "255\n");
		
		for(y=0; y<zone.size.height; y++)
		{
			for(x=0; x<zone.size.width; x++)
			{
				pos = img.stride * (zone.pos.y + y) + (zone.pos.x + x);
				fprintf(f, "%i\n", img.data[pos]);
			}
		}
	}
	else
	{
		perror("libCV : Unknow image type");
		exit(EXIT_FAILURE);
	}
	
	if(fclose(f)==EOF)
    {
		perror("fclose()");
		exit(EXIT_FAILURE);
    }	
}

